#include "fs.h"
#include "sem.h"
#include "irq.h"
#include "cond.h"
#include "lock.h"
#include "sched.h"
#include "common.h"
#include "screen.h"
#include "barrier.h"
#include "syscall.h"
#include "stdio.h"

int binsem_id_max = 0;
int binsem[MAXLOCK];

void handle_other_exception(void)
{
    int print_location = 11;
    vt100_move_cursor(1, print_location);
	printk("[Error]: Undefined exception: EPC:%x\nCAUSE:%x\n", current_running->context_of_user.cp0_epc, current_running->context_of_user.cp0_cause);
	while(1)
	{}
}

void other_syscall(void){
    int print_location = 12;
    vt100_move_cursor(1, print_location);
	printk("[Error]: Undefined syscall: EPC:%x\nCAUSE:%x\n", current_running->context_of_user.cp0_epc, current_running->context_of_user.cp0_cause);
	while(1)
	{}
}

void system_call_helper(uint64_t fn, uint64_t arg1, uint64_t arg2, uint64_t arg3)
{
    current_running->context_of_user.cp0_epc += 4;
    current_running->context_of_user.reg[2] =  syscall[fn](arg1, arg2, arg3);
}

int sys_spawn(task_info_t *info)
{
    invoke_syscall(SYSCALL_SPAWN, (uint64_t)info, IGNORE, IGNORE);
}

void sys_exit(void)
{
    invoke_syscall(SYSCALL_EXIT, IGNORE, IGNORE, IGNORE);
}

void sys_sleep(uint32_t time)
{
    invoke_syscall(SYSCALL_SLEEP, time, IGNORE, IGNORE);
}

int sys_kill(pid_t pid)
{
    invoke_syscall(SYSCALL_KILL, (uint64_t)pid, IGNORE, IGNORE);
}

int sys_waitpid(pid_t pid)
{
    invoke_syscall(SYSCALL_WAITPID, (uint64_t)pid, IGNORE, IGNORE);
}


void sys_clear(void){
    invoke_syscall(SYSCALL_CLEAR, IGNORE, IGNORE, IGNORE);
}

void sys_ps(void){
    invoke_syscall(SYSCALL_PS, IGNORE, IGNORE, IGNORE);
}

void sys_write(char *buff)
{
    invoke_syscall(SYSCALL_WRITE, (uint64_t)buff, IGNORE, IGNORE);
}

void sys_reflush()
{
    invoke_syscall(SYSCALL_REFLUSH, IGNORE, IGNORE, IGNORE);
}

void sys_move_cursor(int x, int y)
{
    invoke_syscall(SYSCALL_CURSOR, x, y, IGNORE);
}

int binsemop(int binsem_id, int op)
{
	if(op == BINSEM_OP_LOCK)
		do_mutex_lock_acquire(&mutex_lock_list[binsem_id]);
	else if(op == BINSEM_OP_UNLOCK)
		do_mutex_lock_release(&mutex_lock_list[binsem_id]);
	return 0;
}

int binsemget(int key)
{
	int i;
	for(i = 0; i < binsem_id_max; i++)
	{
		if(binsem[i] == key)
			return i;
	}
	binsem[binsem_id_max] = key;
	do_mutex_lock_init(&mutex_lock_list[binsem_id_max]);
    binsem_id_max++;
    int binsem_id;
    binsem_id = binsem_id_max - 1;
    return binsem_id;
}

int sys_binsemop(int binsem_id, int op)
{
    invoke_syscall(SYSCALL_BINSEMOP, binsem_id, op, IGNORE);
}

int sys_binsemget(int key)
{
    invoke_syscall(SYSCALL_BINSEMGET, key, IGNORE, IGNORE);
}

void mutex_lock_init(mutex_lock_t *lock)
{
    invoke_syscall(SYSCALL_MUTEX_LOCK_INIT, (uint64_t)lock, IGNORE, IGNORE);
}

void mutex_lock_acquire(mutex_lock_t *lock)
{
    invoke_syscall(SYSCALL_MUTEX_LOCK_ACQUIRE, (uint64_t)lock, IGNORE, IGNORE);
}

void mutex_lock_release(mutex_lock_t *lock)
{
    invoke_syscall(SYSCALL_MUTEX_LOCK_RELEASE, (uint64_t)lock, IGNORE, IGNORE);
}

void condition_init(condition_t *condition)
{
    invoke_syscall(SYSCALL_CONDITION_INIT, (uint64_t)condition, IGNORE, IGNORE);
}

void condition_wait(mutex_lock_t *lock, condition_t *condition)
{
    invoke_syscall(SYSCALL_CONDITION_WAIT, (uint64_t)lock, (uint64_t)condition, IGNORE);
}
void condition_signal(condition_t *condition)
{
    invoke_syscall(SYSCALL_CONDITION_SIGNAL, (uint64_t)condition, IGNORE, IGNORE);
}

void condition_broadcast(condition_t *condition)
{
    invoke_syscall(SYSCALL_CONDITION_BROADCAST, (uint64_t)condition, IGNORE, IGNORE);
}

void semaphore_init(semaphore_t *s, int val)
{
}
void semaphore_up(semaphore_t *s)
{
}

void semaphore_down(semaphore_t *s)
{
}

void barrier_init(barrier_t *barrier, int goal)
{
    invoke_syscall(SYSCALL_BARRIER_INIT, (uint64_t)barrier, goal, IGNORE);
}

void barrier_wait(barrier_t *barrier)
{
    invoke_syscall(SYSCALL_BARRIER_WAIT, (uint64_t)barrier, IGNORE, IGNORE);
}

int sys_read_shell_buff(char *buff)
{
}

void sys_process_show(void)
{
}
void sys_screen_clear(int line1, int line2)
{
}

void mbox_init()
{
    invoke_syscall(SYSCALL_MBOX_INIT, IGNORE, IGNORE, IGNORE);
}

mailbox_t *mbox_open(char *name)
{
    invoke_syscall(SYSCALL_MBOX_OPEN, (uint64_t)name, IGNORE, IGNORE);
}

void mbox_send(mailbox_t *boxid, void *msg, int msg_length)
{
    invoke_syscall(SYSCALL_MBOX_SEND, (uint64_t)boxid, (uint64_t)msg, (uint64_t)msg_length);
}

void mbox_recv(mailbox_t *boxid, void *msg, int msg_length)
{
    invoke_syscall(SYSCALL_MBOX_REC, (uint64_t)boxid, (uint64_t)msg, (uint64_t)msg_length);
}

pid_t sys_getpid()
{
    invoke_syscall(SYSCALL_GETPID, IGNORE, IGNORE, IGNORE);
}

void sys_mkfs()
{
}

int sys_mkdir(char *name)
{
}

int sys_readdir(char *name)
{
}

int sys_enterdir(char *name)
{
}

int sys_rmdir(char *name)
{
}

int sys_print_fs(char *name)
{
}

int sys_mknod(char *name)
{
}

int sys_fopen(char *name, uint32_t access)
{
}

int sys_fwrite(uint32_t fd, char *buff, uint32_t size)
{
}

int sys_cat(char *name)
{
}

int sys_fread(uint32_t fd, char *buff, uint32_t size)
{
}

int sys_close(uint32_t fd)
{
}

uint32_t sys_net_recv(uint64_t rd, uint64_t rd_phy, uint64_t daddr)
{
}

void sys_net_send(uint64_t td, uint64_t td_phy)
{
}

void sys_init_mac()
{
}